//===--- Integers.swift.gyb -----------------------------------*- swift -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
%{
#
# Utility code for later in this template
#

from __future__ import division
from SwiftIntTypes import all_integer_types, int_max_bits, should_define_truncating_bit_pattern_init
from SwiftFloatingPointTypes import getFtoIBounds

from itertools import chain

# Number of bits in the Builtin.Word type
word_bits = int(CMAKE_SIZEOF_VOID_P) * 8

class struct(object):
  def __init__(self, **kw):
    self.__dict__ = kw
  def __repr__(self):
    return 'struct(%r)' % self.__dict__

binaryArithmetic = {
  'Numeric': [
    struct(operator='+', name='adding',      firstArg='_',  llvmName='add', kind='+'),
    struct(operator='-', name='subtracting', firstArg='_',  llvmName='sub', kind='-'),
    struct(operator='*', name='multiplied',  firstArg='by', llvmName='mul', kind='*'),
  ],
  'BinaryInteger': [
    struct(operator='/', name='divided',     firstArg='by', llvmName='div', kind='/'),
    struct(operator='%', name='remainder',   firstArg='dividingBy', llvmName='rem', kind='/'),
  ],
}

binaryBitwise = [
    struct(operator='&', llvmName='and'),
    struct(operator='|', llvmName='or'),
    struct(operator='^', llvmName='xor'),
]

maskingShifts = [
    struct(
      operator='&>>', nonMaskingOperator='>>', description='right shift',
      helper='_nonMaskingRightShift',
      llvmName=lambda s:['lshr','ashr'][s]),
    struct(
      operator='&<<', nonMaskingOperator='<<', description='left shift',
      helper='_nonMaskingLeftShift',
      llvmName=lambda _: 'shl'),
]

#===-----------------------------------------------------------------------===//
#===--- Operator Documentation --------------------------------------------===//
#===-----------------------------------------------------------------------===//


# documentation for binary operators: +, -, <<, &, etc
def operatorComment(operator, fixedWidth):
    comments = {
        '+': """\
  /// Adds two values and produces their sum.
  ///
  /// The addition operator (`+`) calculates the sum of its two arguments. For
  /// example:
  ///
  ///     1 + 2                   // 3
  ///     -10 + 15                // 5
  ///     -15 + -5                // -20
  ///     21.5 + 3.25             // 24.75
  ///
  /// You cannot use `+` with arguments of different types. To add values of
  /// different types, convert one of the values to the other value's type.
  ///
  ///     let x: Int8 = 21
  ///     let y: Int = 1000000
  ///     Int(x) + y              // 1000021
  ///
""" + ("""\
  /// The sum of the two arguments must be representable in the arguments'
  /// type. In the following example, the result of `21 + 120` is greater than
  /// the maximum representable `Int8` value:
  ///
  ///     x + 120                 // Overflow error
  ///
  /// - Note: Overflow checking is not performed in `-Ounchecked` builds.
  ///
  /// If you want to opt out of overflow checking and wrap the result in case
  /// of any overflow, use the overflow addition operator (`&+`).
  ///
  ///     x &+ 120                // -115
  ///
""" if fixedWidth else '') + """\
  /// - Parameters:
  ///   - lhs: The first value to add.
  ///   - rhs: The second value to add.
""",
        '-': """\
  /// Subtracts one value from another and produces their difference.
  ///
  /// The subtraction operator (`-`) calculates the difference of its two
  /// arguments. For example:
  ///
  ///     8 - 3                   // 5
  ///     -10 - 5                 // -15
  ///     100 - -5                // 105
  ///     10.5 - 100.0            // -89.5
  ///
  /// You cannot use `-` with arguments of different types. To subtract values
  /// of different types, convert one of the values to the other value's type.
  ///
  ///     let x: UInt8 = 21
  ///     let y: UInt = 1000000
  ///     y - UInt(x)             // 999979
  ///
""" + ("""\
  /// The difference of the two arguments must be representable in the
  /// arguments' type. In the following example, the result of `21 - 50` is
  /// less than zero, the minimum representable `UInt8` value:
  ///
  ///     x - 50                  // Overflow error
  ///
  /// - Note: Overflow checking is not performed in `-Ounchecked` builds.
  ///
  /// If you want to opt out of overflow checking and wrap the result in case
  /// of any overflow, use the overflow subtraction operator (`&-`).
  ///
  ///     x &- 50                // 227
  ///
""" if fixedWidth else '') + """\
  /// - Parameters:
  ///   - lhs: A numeric value.
  ///   - rhs: The value to subtract from `lhs`.
""",
        '*': """\
  /// Multiplies two values and produces their product.
  ///
  /// The multiplication operator (`*`) calculates the product of its two
  /// arguments. For example:
  ///
  ///     2 * 3                   // 6
  ///     100 * 21                // 2100
  ///     -10 * 15                // -150
  ///     3.5 * 2.25              // 7.875
  ///
  /// You cannot use `*` with arguments of different types. To multiply values
  /// of different types, convert one of the values to the other value's type.
  ///
  ///     let x: Int8 = 21
  ///     let y: Int = 1000000
  ///     Int(x) * y              // 21000000
  ///
""" + ("""\
  /// The product of the two arguments must be representable in the arguments'
  /// type. In the following example, the result of `21 * 21` is greater than
  /// the maximum representable `Int8` value:
  ///
  ///     x * 21                  // Overflow error
  ///
  /// - Note: Overflow checking is not performed in `-Ounchecked` builds.
  ///
  /// If you want to opt out of overflow checking and wrap the result in case
  /// of any overflow, use the overflow multiplication operator (`&*`).
  ///
  ///     x &* 21                // -115
  ///
""" if fixedWidth else '') + """\
  /// - Parameters:
  ///   - lhs: The first value to multiply.
  ///   - rhs: The second value to multiply.
""",
        '/': """\
  /// Returns the quotient of dividing the first value by the second.
  ///
  /// For integer types, any remainder of the division is discarded.
  ///
  ///     let x = 21 / 5
  ///     // x == 4
  ///
  /// - Parameters:
  ///   - lhs: The value to divide.
  ///   - rhs: The value to divide `lhs` by. `rhs` must not be zero.
""",
        '%': """\
  /// Returns the remainder of dividing the first value by the second.
  ///
  /// The result of the remainder operator (`%`) has the same sign as `lhs` and
  /// has a magnitude less than `rhs.magnitude`.
  ///
  ///     let x = 22 % 5
  ///     // x == 2
  ///     let y = 22 % -5
  ///     // y == 2
  ///     let z = -22 % -5
  ///     // z == -2
  ///
  /// For any two integers `a` and `b`, their quotient `q`, and their remainder
  /// `r`, `a == b * q + r`.
  ///
  /// - Parameters:
  ///   - lhs: The value to divide.
  ///   - rhs: The value to divide `lhs` by. `rhs` must not be zero.
""",
        '&+': """\
  /// Returns the sum of the two given values, wrapping the result in case of
  /// any overflow.
  ///
  /// The overflow addition operator (`&+`) discards any bits that overflow the
  /// fixed width of the integer type. In the following example, the sum of
  /// `100` and `121` is greater than the maximum representable `Int8` value,
  /// so the result is the partial value after discarding the overflowing
  /// bits.
  ///
  ///     let x: Int8 = 10 &+ 21
  ///     // x == 31
  ///     let y: Int8 = 100 &+ 121
  ///     // y == -35 (after overflow)
  ///
  /// For more about arithmetic with overflow operators, see [Overflow
  /// Operators][overflow] in *[The Swift Programming Language][tspl]*.
  ///
  /// [overflow]: https://docs.swift.org/swift-book/LanguageGuide/AdvancedOperators.html#ID37
  /// [tspl]: https://docs.swift.org/swift-book/
  ///
  /// - Parameters:
  ///   - lhs: The first value to add.
  ///   - rhs: The second value to add.
""",
        '&-': """\
  /// Returns the difference of the two given values, wrapping the result in
  /// case of any overflow.
  ///
  /// The overflow subtraction operator (`&-`) discards any bits that overflow
  /// the fixed width of the integer type. In the following example, the
  /// difference of `10` and `21` is less than zero, the minimum representable
  /// `UInt` value, so the result is the partial value after discarding the
  /// overflowing bits.
  ///
  ///     let x: UInt8 = 21 &- 10
  ///     // x == 11
  ///     let y: UInt8 = 10 &- 21
  ///     // y == 245 (after overflow)
  ///
  /// For more about arithmetic with overflow operators, see [Overflow
  /// Operators][overflow] in *[The Swift Programming Language][tspl]*.
  ///
  /// [overflow]: https://docs.swift.org/swift-book/LanguageGuide/AdvancedOperators.html#ID37
  /// [tspl]: https://docs.swift.org/swift-book/
  ///
  /// - Parameters:
  ///   - lhs: A numeric value.
  ///   - rhs: The value to subtract from `lhs`.
""",
        '&*': """\
  /// Returns the product of the two given values, wrapping the result in case
  /// of any overflow.
  ///
  /// The overflow multiplication operator (`&*`) discards any bits that
  /// overflow the fixed width of the integer type. In the following example,
  /// the product of `10` and `50` is greater than the maximum representable
  /// `Int8` value, so the result is the partial value after discarding the
  /// overflowing bits.
  ///
  ///     let x: Int8 = 10 &* 5
  ///     // x == 50
  ///     let y: Int8 = 10 &* 50
  ///     // y == -12 (after overflow)
  ///
  /// For more about arithmetic with overflow operators, see [Overflow
  /// Operators][overflow] in *[The Swift Programming Language][tspl]*.
  ///
  /// [overflow]: https://docs.swift.org/swift-book/LanguageGuide/AdvancedOperators.html#ID37
  /// [tspl]: https://docs.swift.org/swift-book/
  ///
  /// - Parameters:
  ///   - lhs: The first value to multiply.
  ///   - rhs: The second value to multiply.
""",
        '&': """\
  /// Returns the result of performing a bitwise AND operation on the two given
  /// values.
  ///
  /// A bitwise AND operation results in a value that has each bit set to `1`
  /// where *both* of its arguments have that bit set to `1`. For example:
  ///
  ///     let x: UInt8 = 5          // 0b00000101
  ///     let y: UInt8 = 14         // 0b00001110
  ///     let z = x & y             // 0b00000100
  ///     // z == 4
  ///
  /// - Parameters:
  ///   - lhs: An integer value.
  ///   - rhs: Another integer value.
""",
        '|': """\
  /// Returns the result of performing a bitwise OR operation on the two given
  /// values.
  ///
  /// A bitwise OR operation results in a value that has each bit set to `1`
  /// where *one or both* of its arguments have that bit set to `1`. For
  /// example:
  ///
  ///     let x: UInt8 = 5          // 0b00000101
  ///     let y: UInt8 = 14         // 0b00001110
  ///     let z = x | y             // 0b00001111
  ///     // z == 15
  ///
  /// - Parameters:
  ///   - lhs: An integer value.
  ///   - rhs: Another integer value.
""",
        '^': """\
  /// Returns the result of performing a bitwise XOR operation on the two given
  /// values.
  ///
  /// A bitwise XOR operation, also known as an exclusive OR operation, results
  /// in a value that has each bit set to `1` where *one or the other but not
  /// both* of its arguments had that bit set to `1`. For example:
  ///
  ///     let x: UInt8 = 5          // 0b00000101
  ///     let y: UInt8 = 14         // 0b00001110
  ///     let z = x ^ y             // 0b00001011
  ///     // z == 11
  ///
  /// - Parameters:
  ///   - lhs: An integer value.
  ///   - rhs: Another integer value.
""",
        '&>>': """\
  /// Returns the result of shifting a value's binary representation the
  /// specified number of digits to the right, masking the shift amount to the
  /// type's bit width.
  ///
  /// Use the masking right shift operator (`&>>`) when you need to perform a
  /// shift and are sure that the shift amount is in the range
  /// `0..<lhs.bitWidth`. Before shifting, the masking right shift operator
  /// masks the shift to this range. The shift is performed using this masked
  /// value.
  ///
  /// The following example defines `x` as an instance of `UInt8`, an 8-bit,
  /// unsigned integer type. If you use `2` as the right-hand-side value in an
  /// operation on `x`, the shift amount requires no masking.
  ///
  ///     let x: UInt8 = 30                 // 0b00011110
  ///     let y = x &>> 2
  ///     // y == 7                         // 0b00000111
  ///
  /// However, if you use `8` as the shift amount, the method first masks the
  /// shift amount to zero, and then performs the shift, resulting in no change
  /// to the original value.
  ///
  ///     let z = x &>> 8
  ///     // z == 30                        // 0b00011110
  ///
  /// If the bit width of the shifted integer type is a power of two, masking
  /// is performed using a bitmask; otherwise, masking is performed using a
  /// modulo operation.
  ///
  /// - Parameters:
  ///   - lhs: The value to shift.
  ///   - rhs: The number of bits to shift `lhs` to the right. If `rhs` is
  ///     outside the range `0..<lhs.bitWidth`, it is masked to produce a
  ///     value within that range.
""",
        '&<<': """\
  /// Returns the result of shifting a value's binary representation the
  /// specified number of digits to the left, masking the shift amount to the
  /// type's bit width.
  ///
  /// Use the masking left shift operator (`&<<`) when you need to perform a
  /// shift and are sure that the shift amount is in the range
  /// `0..<lhs.bitWidth`. Before shifting, the masking left shift operator
  /// masks the shift to this range. The shift is performed using this masked
  /// value.
  ///
  /// The following example defines `x` as an instance of `UInt8`, an 8-bit,
  /// unsigned integer type. If you use `2` as the right-hand-side value in an
  /// operation on `x`, the shift amount requires no masking.
  ///
  ///     let x: UInt8 = 30                 // 0b00011110
  ///     let y = x &<< 2
  ///     // y == 120                       // 0b01111000
  ///
  /// However, if you use `8` as the shift amount, the method first masks the
  /// shift amount to zero, and then performs the shift, resulting in no change
  /// to the original value.
  ///
  ///     let z = x &<< 8
  ///     // z == 30                        // 0b00011110
  ///
  /// If the bit width of the shifted integer type is a power of two, masking
  /// is performed using a bitmask; otherwise, masking is performed using a
  /// modulo operation.
  ///
  /// - Parameters:
  ///   - lhs: The value to shift.
  ///   - rhs: The number of bits to shift `lhs` to the left. If `rhs` is
  ///     outside the range `0..<lhs.bitWidth`, it is masked to produce a
  ///     value within that range.
""",
        '>>': """\
  /// Returns the result of shifting a value's binary representation the
  /// specified number of digits to the right.
  ///
  /// The `>>` operator performs a *smart shift*, which defines a result for a
  /// shift of any value.
  ///
  /// - Using a negative value for `rhs` performs a left shift using
  ///   `abs(rhs)`.
  /// - Using a value for `rhs` that is greater than or equal to the bit width
  ///   of `lhs` is an *overshift*. An overshift results in `-1` for a
  ///   negative value of `lhs` or `0` for a nonnegative value.
  /// - Using any other value for `rhs` performs a right shift on `lhs` by that
  ///   amount.
  ///
  /// The following example defines `x` as an instance of `UInt8`, an 8-bit,
  /// unsigned integer type. If you use `2` as the right-hand-side value in an
  /// operation on `x`, the value is shifted right by two bits.
  ///
  ///     let x: UInt8 = 30                 // 0b00011110
  ///     let y = x >> 2
  ///     // y == 7                         // 0b00000111
  ///
  /// If you use `11` as `rhs`, `x` is overshifted such that all of its bits
  /// are set to zero.
  ///
  ///     let z = x >> 11
  ///     // z == 0                         // 0b00000000
  ///
  /// Using a negative value as `rhs` is the same as performing a left shift
  /// using `abs(rhs)`.
  ///
  ///     let a = x >> -3
  ///     // a == 240                       // 0b11110000
  ///     let b = x << 3
  ///     // b == 240                       // 0b11110000
  ///
  /// Right shift operations on negative values "fill in" the high bits with
  /// ones instead of zeros.
  ///
  ///     let q: Int8 = -30                 // 0b11100010
  ///     let r = q >> 2
  ///     // r == -8                        // 0b11111000
  ///
  ///     let s = q >> 11
  ///     // s == -1                        // 0b11111111
  ///
  /// - Parameters:
  ///   - lhs: The value to shift.
  ///   - rhs: The number of bits to shift `lhs` to the right.
""",
        '<<': """\
  /// Returns the result of shifting a value's binary representation the
  /// specified number of digits to the left.
  ///
  /// The `<<` operator performs a *smart shift*, which defines a result for a
  /// shift of any value.
  ///
  /// - Using a negative value for `rhs` performs a right shift using
  ///   `abs(rhs)`.
  /// - Using a value for `rhs` that is greater than or equal to the bit width
  ///   of `lhs` is an *overshift*, resulting in zero.
  /// - Using any other value for `rhs` performs a left shift on `lhs` by that
  ///   amount.
  ///
  /// The following example defines `x` as an instance of `UInt8`, an 8-bit,
  /// unsigned integer type. If you use `2` as the right-hand-side value in an
  /// operation on `x`, the value is shifted left by two bits.
  ///
  ///     let x: UInt8 = 30                 // 0b00011110
  ///     let y = x << 2
  ///     // y == 120                       // 0b01111000
  ///
  /// If you use `11` as `rhs`, `x` is overshifted such that all of its bits
  /// are set to zero.
  ///
  ///     let z = x << 11
  ///     // z == 0                         // 0b00000000
  ///
  /// Using a negative value as `rhs` is the same as performing a right shift
  /// with `abs(rhs)`.
  ///
  ///     let a = x << -3
  ///     // a == 3                         // 0b00000011
  ///     let b = x >> 3
  ///     // b == 3                         // 0b00000011
  ///
  /// - Parameters:
  ///   - lhs: The value to shift.
  ///   - rhs: The number of bits to shift `lhs` to the left.
""",
  }
    return comments[operator]

# documentation for assignment operators: +=, -=, <<=, etc
def assignmentOperatorComment(operator, fixedWidth):
    comments = {
        '+': """\
  /// Adds two values and stores the result in the left-hand-side variable.
  ///
""" + ("""\
  /// The sum of the two arguments must be representable in the arguments'
  /// type. In the following example, the result of `21 + 120` is greater than
  /// the maximum representable `Int8` value:
  ///
  ///     var x: Int8 = 21
  ///     x += 120
  ///     // Overflow error
  ///
  /// - Note: Overflow checking is not performed in `-Ounchecked` builds.
  ///
""" if fixedWidth else '') + """\
  /// - Parameters:
  ///   - lhs: The first value to add.
  ///   - rhs: The second value to add.
""",
        '-': """\
  /// Subtracts the second value from the first and stores the difference in the
  /// left-hand-side variable.
  ///
""" + ("""\
  /// The difference of the two arguments must be representable in the
  /// arguments' type. In the following example, the result of `21 - 50` is
  /// less than zero, the minimum representable `UInt8` value:
  ///
  ///     var x: UInt8 = 21
  ///     x - 50
  ///     // Overflow error
  ///
  /// - Note: Overflow checking is not performed in `-Ounchecked` builds.
  ///
""" if fixedWidth else '') + """\
  /// - Parameters:
  ///   - lhs: A numeric value.
  ///   - rhs: The value to subtract from `lhs`.
""",
        '*': """\
  /// Multiplies two values and stores the result in the left-hand-side
  /// variable.
  ///
""" + ("""\
  /// The product of the two arguments must be representable in the arguments'
  /// type. In the following example, the result of `21 * 21` is greater than
  /// the maximum representable `Int8` value:
  ///
  ///     var x: Int8 = 21
  ///     x * 21
  ///     // Overflow error
  ///
  /// - Note: Overflow checking is not performed in `-Ounchecked` builds.
  ///
""" if fixedWidth else '') + """\
  /// - Parameters:
  ///   - lhs: The first value to multiply.
  ///   - rhs: The second value to multiply.
""",
        '/': """\
  /// Divides the first value by the second and stores the quotient in the
  /// left-hand-side variable.
  ///
  /// For integer types, any remainder of the division is discarded.
  ///
  ///     var x = 21
  ///     x /= 5
  ///     // x == 4
  ///
  /// - Parameters:
  ///   - lhs: The value to divide.
  ///   - rhs: The value to divide `lhs` by. `rhs` must not be zero.
""",
        '%': """\
  /// Divides the first value by the second and stores the remainder in the
  /// left-hand-side variable.
  ///
  /// The result has the same sign as `lhs` and has a magnitude less than
  /// `rhs.magnitude`.
  ///
  ///     var x = 22
  ///     x %= 5
  ///     // x == 2
  ///
  ///     var y = 22
  ///     y %= -5
  ///     // y == 2
  ///
  ///     var z = -22
  ///     z %= -5
  ///     // z == -2
  ///
  /// - Parameters:
  ///   - lhs: The value to divide.
  ///   - rhs: The value to divide `lhs` by. `rhs` must not be zero.
""",
        '&+': """\
  /// Adds two values and stores the result in the left-hand-side variable,
  /// wrapping any overflow.
  ///
  /// The masking addition assignment operator (`&+=`) silently wraps any
  /// overflow that occurs during the operation. In the following example, the
  /// sum of `100` and `121` is greater than the maximum representable `Int8`
  /// value, so the result is the partial value after discarding the
  /// overflowing bits.
  ///
  ///     var x: Int8 = 10
  ///     x &+= 21
  ///     // x == 31
  ///     var y: Int8 = 100
  ///     y &+= 121
  ///     // y == -35 (after overflow)
  ///
  /// For more about arithmetic with overflow operators, see [Overflow
  /// Operators][overflow] in *[The Swift Programming Language][tspl]*.
  ///
  /// [overflow]: https://docs.swift.org/swift-book/LanguageGuide/AdvancedOperators.html#ID37
  /// [tspl]: https://docs.swift.org/swift-book/
  ///
  /// - Parameters:
  ///   - lhs: The first value to add.
  ///   - rhs: The second value to add.
""",
        '&-': """\
  /// Subtracts the second value from the first and stores the difference in the
  /// left-hand-side variable, wrapping any overflow.
  ///
  /// The masking subtraction assignment operator (`&-=`) silently wraps any
  /// overflow that occurs during the operation. In the following example, the
  /// difference of `10` and `21` is less than zero, the minimum representable
  /// `UInt` value, so the result is the result is the partial value after
  /// discarding the overflowing bits.
  ///
  ///     var x: Int8 = 21
  ///     x &-= 10
  ///     // x == 11
  ///     var y: UInt8 = 10
  ///     y &-= 21
  ///     // y == 245 (after overflow)
  ///
  /// For more about arithmetic with overflow operators, see [Overflow
  /// Operators][overflow] in *[The Swift Programming Language][tspl]*.
  ///
  /// [overflow]: https://docs.swift.org/swift-book/LanguageGuide/AdvancedOperators.html#ID37
  /// [tspl]: https://docs.swift.org/swift-book/
  ///
  /// - Parameters:
  ///   - lhs: A numeric value.
  ///   - rhs: The value to subtract from `lhs`.
""",
        '&*': """\
  /// Multiplies two values and stores the result in the left-hand-side
  /// variable, wrapping any overflow.
  ///
  /// The masking multiplication assignment operator (`&*=`) silently wraps
  /// any overflow that occurs during the operation. In the following example,
  /// the product of `10` and `50` is greater than the maximum representable
  /// `Int8` value, so the result is the partial value after discarding the
  /// overflowing bits.
  ///
  ///     var x: Int8 = 10
  ///     x &*= 5
  ///     // x == 50
  ///     var y: Int8 = 10
  ///     y &*= 50
  ///     // y == -12 (after overflow)
  ///
  /// For more about arithmetic with overflow operators, see [Overflow
  /// Operators][overflow] in *[The Swift Programming Language][tspl]*.
  ///
  /// [overflow]: https://docs.swift.org/swift-book/LanguageGuide/AdvancedOperators.html#ID37
  /// [tspl]: https://docs.swift.org/swift-book/
  ///
  /// - Parameters:
  ///   - lhs: The first value to multiply.
  ///   - rhs: The second value to multiply.
""",
        '&': """\
  /// Stores the result of performing a bitwise AND operation on the two given
  /// values in the left-hand-side variable.
  ///
  /// A bitwise AND operation results in a value that has each bit set to `1`
  /// where *both* of its arguments have that bit set to `1`. For example:
  ///
  ///     var x: UInt8 = 5          // 0b00000101
  ///     let y: UInt8 = 14         // 0b00001110
  ///     x &= y                    // 0b00000100
  ///
  /// - Parameters:
  ///   - lhs: An integer value.
  ///   - rhs: Another integer value.
""",
        '|': """\
  /// Stores the result of performing a bitwise OR operation on the two given
  /// values in the left-hand-side variable.
  ///
  /// A bitwise OR operation results in a value that has each bit set to `1`
  /// where *one or both* of its arguments have that bit set to `1`. For
  /// example:
  ///
  ///     var x: UInt8 = 5          // 0b00000101
  ///     let y: UInt8 = 14         // 0b00001110
  ///     x |= y                    // 0b00001111
  ///
  /// - Parameters:
  ///   - lhs: An integer value.
  ///   - rhs: Another integer value.
""",
        '^': """\
  /// Stores the result of performing a bitwise XOR operation on the two given
  /// values in the left-hand-side variable.
  ///
  /// A bitwise XOR operation, also known as an exclusive OR operation, results
  /// in a value that has each bit set to `1` where *one or the other but not
  /// both* of its arguments had that bit set to `1`. For example:
  ///
  ///     var x: UInt8 = 5          // 0b00000101
  ///     let y: UInt8 = 14         // 0b00001110
  ///     x ^= y                    // 0b00001011
  ///
  /// - Parameters:
  ///   - lhs: An integer value.
  ///   - rhs: Another integer value.
""",
        '&>>': """\
  /// Calculates the result of shifting a value's binary representation the
  /// specified number of digits to the right, masking the shift amount to the
  /// type's bit width, and stores the result in the left-hand-side variable.
  ///
  /// The `&>>=` operator performs a *masking shift*, where the value passed as
  /// `rhs` is masked to produce a value in the range `0..<lhs.bitWidth`. The
  /// shift is performed using this masked value.
  ///
  /// The following example defines `x` as an instance of `UInt8`, an 8-bit,
  /// unsigned integer type. If you use `2` as the right-hand-side value in an
  /// operation on `x`, the shift amount requires no masking.
  ///
  ///     var x: UInt8 = 30                 // 0b00011110
  ///     x &>>= 2
  ///     // x == 7                         // 0b00000111
  ///
  /// However, if you use `19` as `rhs`, the operation first bitmasks `rhs` to
  /// `3`, and then uses that masked value as the number of bits to shift `lhs`.
  ///
  ///     var y: UInt8 = 30                 // 0b00011110
  ///     y &>>= 19
  ///     // y == 3                         // 0b00000011
  ///
  /// - Parameters:
  ///   - lhs: The value to shift.
  ///   - rhs: The number of bits to shift `lhs` to the right. If `rhs` is
  ///     outside the range `0..<lhs.bitWidth`, it is masked to produce a
  ///     value within that range.
""",
        '&<<': """\
  /// Returns the result of shifting a value's binary representation the
  /// specified number of digits to the left, masking the shift amount to the
  /// type's bit width, and stores the result in the left-hand-side variable.
  ///
  /// The `&<<=` operator performs a *masking shift*, where the value used as
  /// `rhs` is masked to produce a value in the range `0..<lhs.bitWidth`. The
  /// shift is performed using this masked value.
  ///
  /// The following example defines `x` as an instance of `UInt8`, an 8-bit,
  /// unsigned integer type. If you use `2` as the right-hand-side value in an
  /// operation on `x`, the shift amount requires no masking.
  ///
  ///     var x: UInt8 = 30                 // 0b00011110
  ///     x &<<= 2
  ///     // x == 120                       // 0b01111000
  ///
  /// However, if you pass `19` as `rhs`, the method first bitmasks `rhs` to
  /// `3`, and then uses that masked value as the number of bits to shift `lhs`.
  ///
  ///     var y: UInt8 = 30                 // 0b00011110
  ///     y &<<= 19
  ///     // y == 240                       // 0b11110000
  ///
  /// - Parameters:
  ///   - lhs: The value to shift.
  ///   - rhs: The number of bits to shift `lhs` to the left. If `rhs` is
  ///     outside the range `0..<lhs.bitWidth`, it is masked to produce a
  ///     value within that range.
""",
        '>>': """\
  /// Stores the result of shifting a value's binary representation the
  /// specified number of digits to the right in the left-hand-side variable.
  ///
  /// The `>>=` operator performs a *smart shift*, which defines a result for a
  /// shift of any value.
  ///
  /// - Using a negative value for `rhs` performs a left shift using
  ///   `abs(rhs)`.
  /// - Using a value for `rhs` that is greater than or equal to the bit width
  ///   of `lhs` is an *overshift*. An overshift results in `-1` for a
  ///   negative value of `lhs` or `0` for a nonnegative value.
  /// - Using any other value for `rhs` performs a right shift on `lhs` by that
  ///   amount.
  ///
  /// The following example defines `x` as an instance of `UInt8`, an 8-bit,
  /// unsigned integer type. If you use `2` as the right-hand-side value in an
  /// operation on `x`, the value is shifted right by two bits.
  ///
  ///     var x: UInt8 = 30                 // 0b00011110
  ///     x >>= 2
  ///     // x == 7                         // 0b00000111
  ///
  /// If you use `11` as `rhs`, `x` is overshifted such that all of its bits
  /// are set to zero.
  ///
  ///     var y: UInt8 = 30                 // 0b00011110
  ///     y >>= 11
  ///     // y == 0                         // 0b00000000
  ///
  /// Using a negative value as `rhs` is the same as performing a left shift
  /// using `abs(rhs)`.
  ///
  ///     var a: UInt8 = 30                 // 0b00011110
  ///     a >>= -3
  ///     // a == 240                       // 0b11110000
  ///
  ///     var b: UInt8 = 30                 // 0b00011110
  ///     b <<= 3
  ///     // b == 240                       // 0b11110000
  ///
  /// Right shift operations on negative values "fill in" the high bits with
  /// ones instead of zeros.
  ///
  ///     var q: Int8 = -30                 // 0b11100010
  ///     q >>= 2
  ///     // q == -8                        // 0b11111000
  ///
  ///     var r: Int8 = -30                 // 0b11100010
  ///     r >>= 11
  ///     // r == -1                        // 0b11111111
  ///
  /// - Parameters:
  ///   - lhs: The value to shift.
  ///   - rhs: The number of bits to shift `lhs` to the right.
""",
        '<<': """\
  /// Stores the result of shifting a value's binary representation the
  /// specified number of digits to the left in the left-hand-side variable.
  ///
  /// The `<<` operator performs a *smart shift*, which defines a result for a
  /// shift of any value.
  ///
  /// - Using a negative value for `rhs` performs a right shift using
  ///   `abs(rhs)`.
  /// - Using a value for `rhs` that is greater than or equal to the bit width
  ///   of `lhs` is an *overshift*, resulting in zero.
  /// - Using any other value for `rhs` performs a left shift on `lhs` by that
  ///   amount.
  ///
  /// The following example defines `x` as an instance of `UInt8`, an 8-bit,
  /// unsigned integer type. If you use `2` as the right-hand-side value in an
  /// operation on `x`, the value is shifted left by two bits.
  ///
  ///     var x: UInt8 = 30                 // 0b00011110
  ///     x <<= 2
  ///     // x == 120                       // 0b01111000
  ///
  /// If you use `11` as `rhs`, `x` is overshifted such that all of its bits
  /// are set to zero.
  ///
  ///     var y: UInt8 = 30                 // 0b00011110
  ///     y <<= 11
  ///     // y == 0                         // 0b00000000
  ///
  /// Using a negative value as `rhs` is the same as performing a right shift
  /// with `abs(rhs)`.
  ///
  ///     var a: UInt8 = 30                 // 0b00011110
  ///     a <<= -3
  ///     // a == 3                         // 0b00000011
  ///
  ///     var b: UInt8 = 30                 // 0b00011110
  ///     b >>= 3
  ///     // b == 3                         // 0b00000011
  ///
  /// - Parameters:
  ///   - lhs: The value to shift.
  ///   - rhs: The number of bits to shift `lhs` to the left.
""",
  }
    return comments[operator]

# documentation for overflow-calculating arithmetic methods, indexed
# by the related operator:
#     +   addingReportingOverflow(_:)
#     -   subtractingReportingOverflow(_:)
#     *   multipliedReportingOverflow(by:)
#     /   dividedReportingOverflow(by:)
#     %   remainderReportingOverflow(dividingBy:)
def overflowOperationComment(operator):
    comments = {
        '+': """\
  /// Returns the sum of this value and the given value, along with a Boolean
  /// value indicating whether overflow occurred in the operation.
  ///
  /// - Parameter rhs: The value to add to this value.
  /// - Returns: A tuple containing the result of the addition along with a
  ///   Boolean value indicating whether overflow occurred. If the `overflow`
  ///   component is `false`, the `partialValue` component contains the entire
  ///   sum. If the `overflow` component is `true`, an overflow occurred and
  ///   the `partialValue` component contains the truncated sum of this value
  ///   and `rhs`.
""",
        '-': """\
  /// Returns the difference obtained by subtracting the given value from this
  /// value, along with a Boolean value indicating whether overflow occurred in
  /// the operation.
  ///
  /// - Parameter rhs: The value to subtract from this value.
  /// - Returns: A tuple containing the result of the subtraction along with a
  ///   Boolean value indicating whether overflow occurred. If the `overflow`
  ///   component is `false`, the `partialValue` component contains the entire
  ///   difference. If the `overflow` component is `true`, an overflow occurred
  ///   and the `partialValue` component contains the truncated result of `rhs`
  ///   subtracted from this value.
""",
        '*': """\
  /// Returns the product of this value and the given value, along with a
  /// Boolean value indicating whether overflow occurred in the operation.
  ///
  /// - Parameter rhs: The value to multiply by this value.
  /// - Returns: A tuple containing the result of the multiplication along with
  ///   a Boolean value indicating whether overflow occurred. If the `overflow`
  ///   component is `false`, the `partialValue` component contains the entire
  ///   product. If the `overflow` component is `true`, an overflow occurred and
  ///   the `partialValue` component contains the truncated product of this
  ///   value and `rhs`.
""",
        '/': """\
  /// Returns the quotient obtained by dividing this value by the given value,
  /// along with a Boolean value indicating whether overflow occurred in the
  /// operation.
  ///
  /// Dividing by zero is not an error when using this method. For a value `x`,
  /// the result of `x.dividedReportingOverflow(by: 0)` is `(x, true)`.
  ///
  /// - Parameter rhs: The value to divide this value by.
  /// - Returns: A tuple containing the result of the division along with a
  ///   Boolean value indicating whether overflow occurred. If the `overflow`
  ///   component is `false`, the `partialValue` component contains the entire
  ///   quotient. If the `overflow` component is `true`, an overflow occurred
  ///   and the `partialValue` component contains either the truncated quotient
  ///   or, if the quotient is undefined, the dividend.
""",
        '%': """\
  /// Returns the remainder after dividing this value by the given value, along
  /// with a Boolean value indicating whether overflow occurred during division.
  ///
  /// Dividing by zero is not an error when using this method. For a value `x`,
  /// the result of `x.remainderReportingOverflow(dividingBy: 0)` is
  /// `(x, true)`.
  ///
  /// - Parameter rhs: The value to divide this value by.
  /// - Returns: A tuple containing the result of the operation along with a
  ///   Boolean value indicating whether overflow occurred. If the `overflow`
  ///   component is `false`, the `partialValue` component contains the entire
  ///   remainder. If the `overflow` component is `true`, an overflow occurred
  ///   during division and the `partialValue` component contains either the
  ///   entire remainder or, if the remainder is undefined, the dividend.
""",
    }
    return comments[operator]

# documentation for "unsafe" arithmetic methods, indexed by the related
# operator:
#     +   unsafeAdding(_:)
#     -   unsafeSubtracting(_:)
#     *   unsafeMultiplied(by:)
#     /   unsafeDivided(by:)
def unsafeOperationComment(operator):
    comments = {
        '+': """\
  /// Returns the sum of this value and the given value without checking for
  /// arithmetic overflow.
  ///
  /// Use this function only to avoid the cost of overflow checking when you
  /// are certain that the operation won't overflow. In optimized builds (`-O`)
  /// the compiler is free to assume that overflow won't occur. Failure to
  /// satisfy that assumption is a serious programming error and could lead to
  /// statements being unexpectedly executed or skipped.
  ///
  /// In debug builds (`-Onone`) a runtime error is still triggered if the
  /// operation overflows.
  ///
  /// This method is not a synonym for the masking addition operator (`&+`).
  /// Use that operator instead of this method when you want to discard any
  /// overflow that results from an addition operation.
  ///
  /// - Parameter rhs: The value to add to this value.
  /// - Returns: The sum of this value and `rhs`.
""",
        '-': """\
  /// Returns the difference obtained by subtracting the given value from this
  /// value without checking for arithmetic overflow.
  ///
  /// Use this function only to avoid the cost of overflow checking when you
  /// are certain that the operation won't overflow. In optimized builds (`-O`)
  /// the compiler is free to assume that overflow won't occur. Failure to
  /// satisfy that assumption is a serious programming error and could lead to
  /// statements being unexpectedly executed or skipped.
  ///
  /// In debug builds (`-Onone`) a runtime error is still triggered if the
  /// operation overflows.
  ///
  /// This method is not a synonym for the masking subtraction operator (`&-`).
  /// Use that operator instead of this method when you want to discard any
  /// overflow that results from a subtraction operation.
  ///
  /// - Parameter rhs: The value to subtract from this value.
  /// - Returns: The result of subtracting `rhs` from this value.
""",
        '*': """\
  /// Returns the product of this value and the given value without checking
  /// for arithmetic overflow.
  ///
  /// Use this function only to avoid the cost of overflow checking when you
  /// are certain that the operation won't overflow. In optimized builds (`-O`)
  /// the compiler is free to assume that overflow won't occur. Failure to
  /// satisfy that assumption is a serious programming error and could lead to
  /// statements being unexpectedly executed or skipped.
  ///
  /// In debug builds (`-Onone`) a runtime error is still triggered if the
  /// operation overflows.
  ///
  /// This method is not a synonym for the masking multiplication operator
  /// (`&*`). Use that operator instead of this method when you want to discard
  /// any overflow that results from an addition operation.
  ///
  /// - Parameter rhs: The value to multiply by this value.
  /// - Returns: The product of this value and `rhs`.
""",
        '/': """\
  /// Returns the quotient obtained by dividing this value by the given value
  /// without checking for arithmetic overflow.
  ///
  /// Use this function only to avoid the cost of overflow checking when you
  /// are certain that the operation won't overflow. In optimized builds (`-O`)
  /// the compiler is free to assume that overflow won't occur. Failure to
  /// satisfy that assumption is a serious programming error and could lead to
  /// statements being unexpectedly executed or skipped.
  ///
  /// In debug builds (`-Onone`) a runtime error is still triggered if the
  /// operation overflows.
  ///
  /// - Parameter rhs: The value to divide this value by.
  /// - Returns: The result of dividing this value by `rhs`.
""",
    }
    return comments[operator]

}%

//===----------------------------------------------------------------------===//
//===--- Concrete FixedWidthIntegers --------------------------------------===//
//===----------------------------------------------------------------------===//

% for self_type in all_integer_types(word_bits):
%   bits = self_type.bits
%   signed = self_type.is_signed
%   BuiltinName = self_type.builtin_name
%   Self = self_type.stdlib_name
%   OtherSelf = self_type.get_opposite_signedness().stdlib_name
%   Unsigned = 'Signed' if signed else 'Unsigned'
%   u = 's' if signed else 'u'
%   U = 'U' if signed else ''
%   z = 's' if signed else 'z'

%   Article = 'An' if bits == 8 else 'A'
%   if self_type.is_word:
/// ${'A ' if signed else 'An un'}signed integer value type.
///
/// On 32-bit platforms, `${Self}` is the same size as `${Self}32`, and
/// on 64-bit platforms, `${Self}` is the same size as `${Self}64`.
%   else:
/// ${Article} ${bits}-bit ${'' if signed else 'un'}signed integer value
/// type.
%   end
@frozen
public struct ${Self}
  : FixedWidthInteger, ${Unsigned}Integer,
    _ExpressibleByBuiltinIntegerLiteral {

  /// A type that represents an integer literal.
  public typealias IntegerLiteralType = ${Self}


  @_transparent
  public init(_builtinIntegerLiteral x: Builtin.IntLiteral) {
    _value = Builtin.s_to_${u}_checked_trunc_IntLiteral_${BuiltinName}(x).0
  }

  /// Creates a new instance with the same memory representation as the given
  /// value.
  ///
  /// This initializer does not perform any range or overflow checking. The
  /// resulting instance may not have the same numeric value as
  /// `bitPattern`---it is only guaranteed to use the same pattern of bits in
  /// its binary representation.
  ///
  /// - Parameter x: A value to use as the source of the new instance's binary
  ///   representation.
  @_transparent
  public init(bitPattern x: ${OtherSelf}) {
    _value = x._value
  }

%   if Self in ['Int32', 'Int64']:
%     Floating = {32: 'Float', 64: 'Double'}[bits]
  @available(*, unavailable,
    message: "Please use ${Self}(bitPattern: ${OtherSelf}) in combination with ${Floating}.bitPattern property.")
  public init(bitPattern x: ${Floating}) {
    Builtin.unreachable()
  }
%   end

%   for (FloatType, FloatBits) in [
%     ('Float16', 16), ('Float', 32), ('Double', 64), ('Float80', 80)]:
%     (lower, upper) = getFtoIBounds(floatBits=FloatBits, intBits=int(bits), signed=signed)

%     if FloatType == 'Float80':
#if !(os(Windows) || os(Android)) && (arch(i386) || arch(x86_64))
%     end

  /// Creates an integer from the given floating-point value, rounding toward
  /// zero.
  ///
  /// Any fractional part of the value passed as `source` is removed, rounding
  /// the value toward zero.
  ///
  ///     let x = Int(21.5)
  ///     // x == 21
  ///     let y = Int(-21.5)
  ///     // y == -21
  ///
  /// If `source` is outside the bounds of this type after rounding toward
  /// zero, a runtime error may occur.
  ///
  ///     let z = UInt(-21.5)
  ///     // Error: ...the result would be less than UInt.min
  ///
  /// - Parameter source: A floating-point value to convert to an integer.
  ///   `source` must be representable in this type after rounding toward
  ///   zero.
%     if FloatType == 'Float16':
  @available(iOS 14.0, watchOS 7.0, tvOS 14.0, *)
  @available(macOS, unavailable)
  @available(macCatalyst, unavailable)
%     end
  @_transparent
  public init(_ source: ${FloatType}) {
    _precondition(source.isFinite,
      "${FloatType} value cannot be converted to ${Self} because it is either infinite or NaN")
%     if not (FloatBits == 16 and bits >= 32): # Float16 is always in-range for 32- and 64-bit ints.
    _precondition(source > ${str(lower)}.0,
      "${FloatType} value cannot be converted to ${Self} because the result would be less than ${Self}.min")
    _precondition(source < ${str(upper)}.0,
      "${FloatType} value cannot be converted to ${Self} because the result would be greater than ${Self}.max")
%     end
    self._value = Builtin.fpto${u}i_FPIEEE${FloatBits}_${BuiltinName}(source._value)
  }

  /// Creates an integer from the given floating-point value, if it can be
  /// represented exactly.
  ///
  /// If the value passed as `source` is not representable exactly, the result
  /// is `nil`. In the following example, the constant `x` is successfully
  /// created from a value of `21.0`, while the attempt to initialize the
  /// constant `y` from `21.5` fails:
  ///
  ///     let x = Int(exactly: 21.0)
  ///     // x == Optional(21)
  ///     let y = Int(exactly: 21.5)
  ///     // y == nil
  ///
  /// - Parameter source: A floating-point value to convert to an integer.
%     if FloatType == 'Float16':
  @available(iOS 14.0, watchOS 7.0, tvOS 14.0, *)
  @available(macOS, unavailable)
  @available(macCatalyst, unavailable)
%     end
  @_transparent
  public init?(exactly source: ${FloatType}) {
    // The value passed as `source` must not be infinite, NaN, or exceed the
    // bounds of the integer type; the result of `fptosi` or `fptoui` is
    // undefined if it overflows.
%     if not (FloatBits == 16 and bits >= 32): # Float16 is always in-range for 32- and 64-bit ints.
    guard source > ${str(lower)}.0 && source < ${str(upper)}.0 else {
      return nil
    }
%     end
    guard source == source.rounded(.towardZero) else {
      return nil
    }
    self._value = Builtin.fpto${u}i_FPIEEE${FloatBits}_${BuiltinName}(source._value)
  }

%     if FloatType == 'Float80':
#endif
%     end

%   end

  @_transparent
  public static func == (lhs: ${Self}, rhs: ${Self}) -> Bool {
    return Bool(Builtin.cmp_eq_Int${bits}(lhs._value, rhs._value))
  }

  @_transparent
  public static func < (lhs: ${Self}, rhs: ${Self}) -> Bool {
    return Bool(Builtin.cmp_${u}lt_Int${bits}(lhs._value, rhs._value))
  }

// See corresponding definitions in the FixedWidthInteger extension.
%       for x in binaryArithmetic['Numeric'] + binaryArithmetic["BinaryInteger"][:1]:
${assignmentOperatorComment(x.operator, True)}
  @_transparent
  public static func ${x.operator}=(lhs: inout ${Self}, rhs: ${Self}) {
%   if x.kind == '/':
    // No LLVM primitives for checking overflow of division operations, so we
    // check manually.
    if _slowPath(rhs == (0 as ${Self})) {
      _preconditionFailure(
        "Division by zero${' in remainder operation' if x.operator == '%' else ''}")
    }
%     if signed:
    if _slowPath(
      ${'lhs == %s.min && rhs == (-1 as %s)' % (Self, Self)}
    ) {
      _preconditionFailure(
        "Division results in an overflow${' in remainder operation' if x.operator == '%' else ''}")
    }
%     end
    let (result, overflow) =
      (Builtin.${u}${x.llvmName}_Int${bits}(lhs._value, rhs._value),
      false._value)
%   else:
    let (result, overflow) =
      Builtin.${u}${x.llvmName}_with_overflow_Int${bits}(
        lhs._value, rhs._value, true._value)
%   end
    Builtin.condfail_message(overflow,
      StaticString("arithmetic overflow").unsafeRawPointer)
    lhs = ${Self}(result)
  }
%       end

%       for x in chain(*binaryArithmetic.values()):

${overflowOperationComment(x.operator)}
  @_transparent
  public func ${x.name}ReportingOverflow(
    ${x.firstArg} other: ${Self}
  ) -> (partialValue: ${Self}, overflow: Bool) {
%         if x.kind == '/':
    // No LLVM primitives for checking overflow of division operations, so we
    // check manually.
    if _slowPath(other == (0 as ${Self})) {
      return (partialValue: self, overflow: true)
    }
%           if signed:
    if _slowPath(self == ${Self}.min && other == (-1 as ${Self})) {
%             partialValue = 'self' if x.operator == '/' else '0'
      return (partialValue: ${partialValue}, overflow: true)
    }
%           end

    let (newStorage, overflow) = (
      Builtin.${u}${x.llvmName}_Int${bits}(self._value, other._value),
      false._value)

%         else:

    let (newStorage, overflow) =
      Builtin.${u}${x.llvmName}_with_overflow_Int${bits}(
        self._value, other._value, false._value)
%         end

    return (
      partialValue: ${Self}(newStorage),
      overflow: Bool(overflow))
  }
%       end

${assignmentOperatorComment('%', True)}
  @_transparent
  public static func %=(lhs: inout ${Self}, rhs: ${Self}) {
    // No LLVM primitives for checking overflow of division operations, so we
    // check manually.
    if _slowPath(rhs == (0 as ${Self})) {
      _preconditionFailure(
        "Division by zero in remainder operation")
    }
%     if signed:
    if _slowPath(${'lhs == %s.min && rhs == (-1 as %s)' % (Self, Self)}) {
      _preconditionFailure(
        "Division results in an overflow in remainder operation")
    }
%     end

    let (newStorage, _) = (
      Builtin.${u}rem_Int${bits}(lhs._value, rhs._value),
      false._value)
    lhs = ${Self}(newStorage)
  }

  @_transparent
  public init(_ _value: Builtin.Int${bits}) {
    self._value = _value
  }

% for x in binaryBitwise:
${assignmentOperatorComment(x.operator, True)}
  @_transparent
  public static func ${x.operator}=(lhs: inout ${Self}, rhs: ${Self}) {
    lhs = ${Self}(Builtin.${x.llvmName}_Int${bits}(lhs._value, rhs._value))
  }
% end

% for x in maskingShifts:

${assignmentOperatorComment(x.operator, True)}
  @_transparent
  public static func ${x.operator}=(lhs: inout ${Self}, rhs: ${Self}) {
    let rhs_ = rhs & ${bits - 1}
    lhs = ${Self}(
      Builtin.${x.llvmName(signed)}_Int${bits}(lhs._value, rhs_._value))
  }

% end

  /// The number of bits used for the underlying binary representation of
  /// values of this type.
  ///
%   if self_type.is_word:
  /// The bit width of ${Article.lower()} `${Self}` instance is 32 on 32-bit
  /// platforms and 64 on 64-bit platforms.
%   else:
  /// The bit width of ${Article.lower()} `${Self}` instance is ${bits}.
%   end
  @_transparent
  public static var bitWidth: Int { return ${bits} }

  /// The number of leading zeros in this value's binary representation.
  ///
  /// For example, in an integer type with a `bitWidth` value of 8,
  /// the number *31* has three leading zeros.
  ///
  ///     let x: Int8 = 0b0001_1111
  ///     // x == 31
  ///     // x.leadingZeroBitCount == 3
  @_transparent
  public var leadingZeroBitCount: Int {
    return Int(
      ${Self}(
        Builtin.int_ctlz_Int${bits}(self._value, false._value)
      )._lowWord._value)
  }

  /// The number of trailing zeros in this value's binary representation.
  ///
  /// For example, the number *-8* has three trailing zeros.
  ///
  ///     let x = Int8(bitPattern: 0b1111_1000)
  ///     // x == -8
  ///     // x.trailingZeroBitCount == 3
  @_transparent
  public var trailingZeroBitCount: Int {
    return Int(
      ${Self}(
        Builtin.int_cttz_Int${bits}(self._value, false._value)
      )._lowWord._value)
  }

  /// The number of bits equal to 1 in this value's binary representation.
  ///
  /// For example, in a fixed-width integer type with a `bitWidth` value of 8,
  /// the number *31* has five bits equal to *1*.
  ///
  ///     let x: Int8 = 0b0001_1111
  ///     // x == 31
  ///     // x.nonzeroBitCount == 5
  @_transparent
  public var nonzeroBitCount: Int {
    return Int(
      ${Self}(
        Builtin.int_ctpop_Int${bits}(self._value)
      )._lowWord._value)
  }

  /// A type that represents the words of this integer.
  @frozen
  public struct Words: RandomAccessCollection {
    public typealias Indices = Range<Int>
    public typealias SubSequence = Slice<${Self}.Words>

    @usableFromInline
    internal var _value: ${Self}

    @inlinable
    public init(_ value: ${Self}) {
      self._value = value
    }

    @inlinable
    public var count: Int {
      return (${bits} + ${word_bits} - 1) / ${word_bits}
    }

    @inlinable
    public var startIndex: Int { return 0 }

    @inlinable
    public var endIndex: Int { return count }

    @inlinable
    public var indices: Indices { return startIndex ..< endIndex }

    @_transparent
    public func index(after i: Int) -> Int { return i + 1 }

    @_transparent
    public func index(before i: Int) -> Int { return i - 1 }

    @inlinable
    public subscript(position: Int) -> UInt {
      get {
        _precondition(position >= 0, "Negative word index")
        _precondition(position < endIndex, "Word index out of range")
        let shift = UInt(position._value) &* ${word_bits}
        _internalInvariant(shift < UInt(_value.bitWidth._value))
        return (_value &>> ${Self}(_truncatingBits: shift))._lowWord
      }
    }
  }

  /// A collection containing the words of this value's binary
  /// representation, in order from the least significant to most significant.
% if signed:
  ///
  /// Negative values are returned in two's complement representation,
  /// regardless of the type's underlying implementation.
% end
  @_transparent
  public var words: Words {
    return Words(self)
  }

  @_transparent
  public // transparent
  var _lowWord: UInt {
    % truncOrExt = z + 'ext' if bits <= word_bits else 'trunc'
    return UInt(
      Builtin.${truncOrExt}OrBitCast_Int${bits}_Int${word_bits}(_value)
    )
  }

  @_transparent
  public // transparent
  init(_truncatingBits bits: UInt) {
    % truncOrExt = 'zext' if bits > word_bits else 'trunc'
    self.init(
      Builtin.${truncOrExt}OrBitCast_Int${word_bits}_Int${bits}(bits._value))
  }

  /// A type that can represent the absolute value of any possible value of
  /// this type.
  public typealias Magnitude = ${U}${Self}

% if signed:
  /// The magnitude of this value.
  ///
  /// For any numeric value `x`, `x.magnitude` is the absolute value of `x`.
  /// You can use the `magnitude` property in operations that are simpler to
  /// implement in terms of unsigned values, such as printing the value of an
  /// integer, which is just printing a '-' character in front of an absolute
  /// value.
  ///
  ///     let x = -200
  ///     // x.magnitude == 200
  ///
  /// The global `abs(_:)` function provides more familiar syntax when you need
  /// to find an absolute value. In addition, because `abs(_:)` always returns
  /// a value of the same type, even in a generic context, using the function
  /// instead of the `magnitude` property is encouraged.
  @_transparent
  public var magnitude: U${Self} {
    let base = U${Self}(_value)
    return self < (0 as ${Self}) ? ~base &+ 1 : base
  }
% end

%   dbits = bits*2
%   if bits <= word_bits:
  /// Returns a tuple containing the high and low parts of the result of
  /// multiplying this value by the given value.
  ///
  /// Use this method to calculate the full result of a product that would
  /// otherwise overflow. Unlike traditional truncating multiplication, the
  /// `multipliedFullWidth(by:)` method returns a tuple
  /// containing both the `high` and `low` parts of the product of this value and
  /// `other`. The following example uses this method to multiply two `UInt8`
  /// values that normally overflow when multiplied:
  ///
  ///     let x: UInt8 = 100
  ///     let y: UInt8 = 20
  ///     let result = x.multipliedFullWidth(by: y)
  ///     // result.high == 0b00000111
  ///     // result.low  == 0b11010000
  ///
  /// The product of `x` and `y` is 2000, which is too large to represent in a
  /// `UInt8` instance. The `high` and `low` properties of the `result` value
  /// represent 2000 when concatenated to form a double-width integer; that
  /// is, using `result.high` as the high byte and `result.low` as the low byte
  /// of a `UInt16` instance.
  ///
  ///     let z = UInt16(result.high) << 8 | UInt16(result.low)
  ///     // z == 2000
  ///
  /// - Parameter other: The value to multiply this value by.
  /// - Returns: A tuple containing the high and low parts of the result of
  ///   multiplying this value and `other`.
  @inlinable
  public func multipliedFullWidth(by other: ${Self})
    -> (high: ${Self}, low: ${Self}.Magnitude) {
    // FIXME(integers): tests
    let lhs_ = Builtin.${z}ext_Int${bits}_Int${dbits}(self._value)
    let rhs_ = Builtin.${z}ext_Int${bits}_Int${dbits}(other._value)

    let res = Builtin.mul_Int${dbits}(lhs_, rhs_)
    let low = ${Self}.Magnitude(Builtin.truncOrBitCast_Int${dbits}_Int${bits}(res))
    let shift = Builtin.zextOrBitCast_Int8_Int${dbits}(UInt8(${bits})._value)
    let shifted = Builtin.ashr_Int${dbits}(res, shift)
    let high = ${Self}(Builtin.truncOrBitCast_Int${dbits}_Int${bits}(shifted))
    return (high: high, low: low)
  }
%   end

  /// Returns a tuple containing the quotient and remainder of dividing the
  /// given value by this value.
  ///
  /// The resulting quotient must be representable within the bounds of the
  /// type. If the quotient of dividing `dividend` by this value is too large
  /// to represent in the type, a runtime error may occur.
  ///
  /// - Parameter dividend: A tuple containing the high and low parts of a
  ///   double-width integer. The `high` component of the value carries the
  ///   sign, if the type is signed.
  /// - Returns: A tuple containing the quotient and remainder of `dividend`
  ///   divided by this value.
  @inlinable
  public func dividingFullWidth(
    _ dividend: (high: ${Self}, low: ${Self}.Magnitude)
  ) -> (quotient: ${Self}, remainder: ${Self}) {
    // FIXME(integers): tests
%   # 128-bit types are not provided by the 32-bit LLVM
%   if word_bits == 32 and bits == 64:
%   # FIXME(integers): uncomment the above after using the right conditional
%   # compilation block to exclude 64-bit Windows, which does not support
%   # 128-bit operations
    fatalError("Operation is not supported")
%   else:
    // FIXME(integers): handle division by zero and overflows
    _precondition(self != 0, "Division by zero")
    let lhsHigh = Builtin.${z}ext_Int${bits}_Int${dbits}(dividend.high._value)
    let shift = Builtin.zextOrBitCast_Int8_Int${dbits}(UInt8(${bits})._value)
    let lhsHighShifted = Builtin.shl_Int${dbits}(lhsHigh, shift)
    let lhsLow = Builtin.zext_Int${bits}_Int${dbits}(dividend.low._value)
    let lhs_ = Builtin.or_Int${dbits}(lhsHighShifted, lhsLow)
    let rhs_ = Builtin.${z}ext_Int${bits}_Int${dbits}(self._value)

    let quotient_ = Builtin.${u}div_Int${dbits}(lhs_, rhs_)
    let remainder_ = Builtin.${u}rem_Int${dbits}(lhs_, rhs_)

    let quotient = ${Self}(
      Builtin.truncOrBitCast_Int${dbits}_Int${bits}(quotient_))
    let remainder = ${Self}(
      Builtin.truncOrBitCast_Int${dbits}_Int${bits}(remainder_))

    return (quotient: quotient, remainder: remainder)
%   end
  }

  /// A representation of this integer with the byte order swapped.
  @_transparent
  public var byteSwapped: ${Self} {
%   if bits <= 8:
    return self
%   else:
    return ${Self}(Builtin.int_bswap_${BuiltinName}(_value))
%   end
  }

  // Implementation details

  public var _value: Builtin.Int${bits}

% if self_type.is_word:
  @_transparent
  public // @testable
  init(_ _v: Builtin.Word) {
% if BuiltinName == 'Int32':
    self._value = Builtin.truncOrBitCast_Word_Int32(_v)
% elif BuiltinName == 'Int64':
    self._value = Builtin.${z}extOrBitCast_Word_Int64(_v)
% end
  }

  @_transparent
  public // @testable
  var _builtinWordValue: Builtin.Word {
% if BuiltinName == 'Int32':
    return Builtin.${z}extOrBitCast_Int32_Word(_value)
% elif BuiltinName == 'Int64':
    return Builtin.truncOrBitCast_Int64_Word(_value)
% end
  }
% end

  /// Returns `-1` if this value is negative and `1` if it's positive;
  /// otherwise, `0`.
  ///
  /// - Returns: The sign of this number, expressed as an integer of the same
  ///   type.
  @inlinable
  @inline(__always)
  public func signum() -> ${Self} {
    let isPositive = ${Self}(Builtin.zext_Int1_Int${bits}(
      (self > (0 as ${Self}))._value))
    return isPositive | (self &>> ${bits - 1})
  }
}
%# end of concrete type: ${Self}

extension ${Self}: Hashable {
  /// Hashes the essential components of this value by feeding them into the
  /// given hasher.
  ///
  /// - Parameter hasher: The hasher to use when combining the components
  ///   of this instance.
  @inlinable
  public func hash(into hasher: inout Hasher) {
    hasher._combine(${U}${Self}(_value))
  }

  @inlinable
  public func _rawHashValue(seed: Int) -> Int {
    % if bits == 64:
    return Hasher._hash(seed: seed, UInt64(_value))
    % elif bits == word_bits:
    return Hasher._hash(seed: seed, UInt(_value))
    % else:
    return Hasher._hash(
      seed: seed,
      bytes: UInt64(truncatingIfNeeded: ${U}${Self}(_value)),
      count: ${bits // 8})
    % end
  }
}

extension ${Self}: _HasCustomAnyHashableRepresentation {
  // Not @inlinable
  public func _toCustomAnyHashable() -> AnyHashable? {
    return AnyHashable(_box: _IntegerAnyHashableBox(self))
  }
}

// FIXME(integers): this section here is to help the typechecker,
// as it seems to have problems with a pattern where the nonmutating operation
// is defined on a protocol in terms of a mutating one that is itself defined
// on concrete types.
extension ${Self} {

%   for x in binaryBitwise + maskingShifts + list(chain(*binaryArithmetic.values())):

${operatorComment(x.operator, True)}
  @_transparent
  public static func ${x.operator}(lhs: ${Self}, rhs: ${Self}) -> ${Self} {
    var lhs = lhs
    lhs ${x.operator}= rhs
    return lhs
  }

%   end

  @_transparent
  public static func <= (lhs: ${Self}, rhs: ${Self}) -> Bool {
    return !(rhs < lhs)
  }

  @_transparent
  public static func >= (lhs: ${Self}, rhs: ${Self}) -> Bool {
    return !(lhs < rhs)
  }

  @_transparent
  public static func > (lhs: ${Self}, rhs: ${Self}) -> Bool {
    return rhs < lhs
  }
}


% if signed:
// TODO: Consider removing the underscore.
/// Returns the argument and specifies that the value is not negative.
/// It has only an effect if the argument is a load or call.
@_transparent
public func _assumeNonNegative(_ x: ${Self}) -> ${Self} {
  _internalInvariant(x >= (0 as ${Self}))
  return ${Self}(Builtin.assumeNonNegative_${BuiltinName}(x._value))
}
% end

//===--- end of FIXME(integers) -------------------------------------------===//

% end # end of concrete FixedWidthInteger section

extension Int {
  // FIXME(ABI): using Int as the return type is wrong.
  /// Returns the distance from this value to the given value, expressed as a
  /// stride.
  ///
  /// For two values `x` and `y`, and a distance `n = x.distance(to: y)`,
  /// `x.advanced(by: n) == y`.
  ///
  /// - Parameter other: The value to calculate the distance to.
  /// - Returns: The distance from this value to `other`.
  @_transparent
  public func distance(to other: Int) -> Int {
    return other - self
  }

  // FIXME(ABI): using Int as the parameter type is wrong.
  /// Returns a value that is offset the specified distance from this value.
  ///
  /// Use the `advanced(by:)` method in generic code to offset a value by a
  /// specified distance. If you're working directly with numeric values, use
  /// the addition operator (`+`) instead of this method.
  ///
  /// For a value `x`, a distance `n`, and a value `y = x.advanced(by: n)`,
  /// `x.distance(to: y) == n`.
  ///
  /// - Parameter n: The distance to advance this value.
  /// - Returns: A value that is offset from this value by `n`.
  @_transparent
  public func advanced(by n: Int) -> Int {
    return self + n
  }
}

// FIXME(integers): switch to using `FixedWidthInteger.unsafeAdding`
@_transparent
@inlinable
internal func _unsafePlus(_ lhs: Int, _ rhs: Int) -> Int {
#if INTERNAL_CHECKS_ENABLED
  return lhs + rhs
#else
  return lhs &+ rhs
#endif
}

// FIXME(integers): switch to using `FixedWidthInteger.unsafeSubtracting`
@_transparent
@inlinable
internal func _unsafeMinus(_ lhs: Int, _ rhs: Int) -> Int {
#if INTERNAL_CHECKS_ENABLED
  return lhs - rhs
#else
  return lhs &- rhs
#endif
}

internal struct _IntegerAnyHashableBox<
  Base: FixedWidthInteger
>: _AnyHashableBox {
  internal let _value: Base

  internal init(_ value: Base) {
    self._value = value
  }

  internal var _canonicalBox: _AnyHashableBox {
    // We need to follow NSNumber semantics here; the AnyHashable forms of
    // integer types holding the same mathematical value should compare equal.
    // Sign-extend value to a 64-bit integer. This will generate hash conflicts
    // between, say -1 and UInt.max, but that's fine.
    if _value < 0 {
      return _IntegerAnyHashableBox<Int64>(Int64(truncatingIfNeeded: _value))
    }
    return _IntegerAnyHashableBox<UInt64>(UInt64(truncatingIfNeeded: _value))
  }

  internal func _isEqual(to box: _AnyHashableBox) -> Bool? {
    if Base.self == UInt64.self {
      guard let box = box as? _IntegerAnyHashableBox<UInt64> else { return nil }
      return _value == box._value
    }
    if Base.self == Int64.self {
      guard let box = box as? _IntegerAnyHashableBox<Int64> else { return nil }
      return _value == box._value
    }
    _preconditionFailure("self isn't canonical")
  }

  internal var _hashValue: Int {
    _internalInvariant(Base.self == UInt64.self || Base.self == Int64.self,
      "self isn't canonical")
    return _value.hashValue
  }

  internal func _hash(into hasher: inout Hasher) {
    _internalInvariant(Base.self == UInt64.self || Base.self == Int64.self,
      "self isn't canonical")
    _value.hash(into: &hasher)
  }

  internal func _rawHashValue(_seed: Int) -> Int {
    _internalInvariant(Base.self == UInt64.self || Base.self == Int64.self,
      "self isn't canonical")
    return _value._rawHashValue(seed: _seed)
  }

  internal var _base: Any {
    return _value
  }

  internal func _unbox<T: Hashable>() -> T? {
    return _value as? T
  }

  internal func _downCastConditional<T>(
    into result: UnsafeMutablePointer<T>
  ) -> Bool {
    guard let value = _value as? T else { return false }
    result.initialize(to: value)
    return true
  }
}

// ${'Local Variables'}:
// eval: (read-only-mode 1)
// End:
